package section

import (
	"context"
	"strconv"
	"strings"

	"mall/common/globalkey"
	"mall/common/utils/pointy"
	"mall/service/backend/api/internal/logic/system/util"
	"mall/service/backend/api/internal/logic/utils"
	"mall/service/backend/api/internal/logic/utils/parse"
	"mall/service/backend/api/internal/svc"
	"mall/service/backend/api/internal/types"
	"mall/service/backend/common/enum/errorcode"
	"mall/service/backend/common/errorx"
	"mall/service/backend/common/i18n"
	"mall/service/backend/rpc/backendclient"
	"mall/service/blog/rpc/blogclient"
	"mall/service/forum/rpc/forumclient"

	"github.com/zeromicro/go-zero/core/logx"
)

type GetSectionPostListLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

func NewGetSectionPostListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetSectionPostListLogic {
	return &GetSectionPostListLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}

func (l *GetSectionPostListLogic) GetSectionPostList(req *types.SectionKBPostListReq) (*types.SectionKBPostListResp, error) {
	if req.SectionId == nil || *req.SectionId == 0 {
		return nil, errorx.NewCodeError(errorcode.InvalidArgument,
			l.svcCtx.Trans.Trans(l.ctx, "common.validationError"))
	}

	page, pageSize := parse.ParsePageInfo(
		req.Current,
		req.PageSize,
		l.svcCtx.Config.Query.DefaultAmount,
		l.svcCtx.Config.Query.MaxAmount,
	)

	orderBys := util.ParseSorter(req.Sorter)
	filterBys := util.ParseFilter(req.Filter)

	res, err := l.svcCtx.BackendRpc.BackendGetSectionPostList(l.ctx, &backendclient.SectionPostListReq{
		Page:      page,
		PageSize:  pageSize,
		SectionId: req.SectionId,
		PostType:  req.PostType,
		OrderBy:   orderBys,
		FilterBy:  filterBys,
	})
	if err != nil {
		return nil, err
	}

	resp := &types.SectionKBPostListResp{
		BaseDataInfo: types.BaseDataInfo{
			Success: true,
			Msg:     l.svcCtx.Trans.Trans(l.ctx, i18n.Success),
		},
		Data: types.SectionKBPostListInfo{
			BaseListInfo: types.BaseListInfo{
				Current:  page,
				PageSize: pageSize,
			},
		},
	}
	var total uint64

	if len(res.List) > 0 {
		var ids []string
		var rids []string
		var pids []string
		idSortMap := make(map[uint64]*uint32)
		ridSortMap := make(map[uint64]*uint32)
		pidSortMap := make(map[uint64]*uint32)
		for _, v := range res.List {
			if v.PostId != nil && *v.PostId > 0 {
				if v.PostType != nil && *v.PostType > 0 {
					if *v.PostType == uint32(globalkey.SettingSectionTypeForumPostIndex) {
						rids = append(rids, strconv.FormatInt(int64(*v.PostId), 10))
						ridSortMap[*v.PostId] = v.Sort
					} else if *v.PostType == uint32(globalkey.SettingSectionTypeEntryIndex) {
						ids = append(ids, strconv.FormatInt(int64(*v.PostId), 10))
						idSortMap[*v.PostId] = v.Sort
					} else if *v.PostType == uint32(globalkey.SettingSectionTypePostIndex) {
						pids = append(pids, strconv.FormatInt(int64(*v.PostId), 10))
						pidSortMap[*v.PostId] = v.Sort
					}
				}
			}
		}

		if len(rids) > 0 {
			data, err := l.svcCtx.ForumRpc.BackendGetPostList(l.ctx, &forumclient.BackendPostListReq{
				Ids:      pointy.GetPointer(strings.Join(rids, ",")),
				WithMeta: req.WithMeta,
			})
			if err != nil {
				return nil, err
			}

			if len(data.List) > 0 {
				total = uint64(len(data.List))
				for _, v := range data.List {
					var media []*types.MediaInfo

					if len(v.Media) > 0 {
						for _, m := range v.Media {
							var url string
							if m.Url != nil && len(*m.Url) > 0 {
								url = *m.Url
							}
							if len(url) == 0 && m.Uri != nil && len(*m.Uri) > 0 {
								url = *m.Uri
							}
							filename, mimeType, metaData := utils.ParseMetaData(m.MetaData)
							media = append(media, &types.MediaInfo{
								Uid:       m.Uid,
								Id:        m.Id,
								Thumbnail: m.Thumbnail,
								Order:     m.Order,
								Url:       pointy.GetPointer(url),
								Name:      pointy.GetPointer(filename),
								MimeType:  pointy.GetPointer(mimeType),
								AltText:   m.AltText,
								MetaData:  pointy.GetPointer(metaData),
							})
						}
					}

					resp.Data.List = append(resp.Data.List, &types.SectionKBPostInfo{
						Id:     v.Id,
						Title:  v.PostTitle,
						Status: v.Status,
						Sort:   v.Sort,
						Media:  media,
					})
				}
			}
		}

		if len(ids) > 0 {
			data, err := l.svcCtx.BlogRpc.BackendGetKBPostList(l.ctx, &blogclient.TmpKBPostListReq{
				Ids:      pointy.GetPointer(strings.Join(ids, ",")),
				WithMeta: pointy.GetPointer(uint32(1)),
			})
			if err != nil {
				return nil, err
			}

			if len(data.List) > 0 {
				total = uint64(len(data.List))
				for _, v := range data.List {
					var media []*types.MediaInfo
					if len(v.Media) > 0 {
						for _, m := range v.Media {
							var url string
							if m.Url != nil && len(*m.Url) > 0 {
								url = *m.Url
							}
							if len(url) == 0 && m.Uri != nil && len(*m.Uri) > 0 {
								url = *m.Uri
							}
							filename, mimeType, metaData := utils.ParseMetaData(m.MetaData)
							media = append(media, &types.MediaInfo{
								Uid:       m.Uid,
								Id:        m.Id,
								Thumbnail: m.Thumbnail,
								Order:     m.Order,
								Url:       pointy.GetPointer(url),
								Name:      pointy.GetPointer(filename),
								MimeType:  pointy.GetPointer(mimeType),
								AltText:   m.AltText,
								MetaData:  pointy.GetPointer(metaData),
							})
						}
					}

					if len(v.Media) > 0 {
						for _, m := range v.Media {
							var url string
							if m.Url != nil && len(*m.Url) > 0 {
								url = *m.Url
							}
							if len(url) == 0 && m.Uri != nil && len(*m.Uri) > 0 {
								url = *m.Uri
							}
							filename, mimeType, metaData := utils.ParseMetaData(m.MetaData)
							media = append(media, &types.MediaInfo{
								Uid:       m.Uid,
								Id:        m.Id,
								Thumbnail: m.Thumbnail,
								Order:     m.Order,
								Url:       pointy.GetPointer(url),
								Name:      pointy.GetPointer(filename),
								MimeType:  pointy.GetPointer(mimeType),
								AltText:   m.AltText,
								MetaData:  pointy.GetPointer(metaData),
							})
						}
					}

					resp.Data.List = append(resp.Data.List, &types.SectionKBPostInfo{
						Id:     v.Id,
						Title:  v.Title,
						Slug:   v.Slug,
						Sort:   v.Sort,
						Status: v.Status,
						Media:  media,
					})
				}
			}
		}

		if len(pids) > 0 {
			data, err := l.svcCtx.BlogRpc.BackendGetPostList(l.ctx, &blogclient.TmpPostListReq{
				Ids:      pointy.GetPointer(strings.Join(pids, ",")),
				WithMeta: req.WithMeta,
			})
			if err != nil {
				return nil, err
			}

			if len(data.List) > 0 {
				total = uint64(len(data.List))
				for _, v := range data.List {
					var media []*types.MediaInfo

					if len(v.Media) > 0 {
						for _, m := range v.Media {
							var url string
							if m.Url != nil && len(*m.Url) > 0 {
								url = *m.Url
							}
							if len(url) == 0 && m.Uri != nil && len(*m.Uri) > 0 {
								url = *m.Uri
							}
							filename, mimeType, metaData := utils.ParseMetaData(m.MetaData)
							media = append(media, &types.MediaInfo{
								Uid:       m.Uid,
								Id:        m.Id,
								Thumbnail: m.Thumbnail,
								Order:     m.Order,
								Url:       pointy.GetPointer(url),
								Name:      pointy.GetPointer(filename),
								MimeType:  pointy.GetPointer(mimeType),
								AltText:   m.AltText,
								MetaData:  pointy.GetPointer(metaData),
							})
						}
					}

					resp.Data.List = append(resp.Data.List, &types.SectionKBPostInfo{
						Id:     v.Id,
						Title:  v.Title,
						Status: v.Status,
						Sort:   v.Sort,
						Media:  media,
					})
				}
			}
		}
		resp.Data.Total = total
	}

	return resp, nil
}
